package im.vinci.server.feed.service;

import im.vinci.server.common.domain.music.MusicSong;
import im.vinci.server.common.exceptions.VinciException;
import im.vinci.server.common.exceptions.error.ErrorCode;
import im.vinci.server.feed.domain.MusicPlayInfo;
import im.vinci.server.feed.domain.UserPlayInfo;
import im.vinci.server.feed.domain.UserPlayTimeInfo;
import im.vinci.server.feed.domain.wrapper.UserPlayInfoDAO;
import im.vinci.server.feed.persistence.UserPlayInfoMapper;
import im.vinci.server.feed.persistence.UserPlayTimeInfoMapper;
import im.vinci.server.user.domain.UserInfo;
import im.vinci.server.user.service.UserLoginAndBindDeviceService;
import im.vinci.server.utils.BizTemplate;
import im.vinci.server.utils.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by mingjie on 17/2/14.
 */
@Service
public class VinciPlayListService {

    @Autowired
    private UserLoginAndBindDeviceService userLoginAndBindDeviceService;

    @Autowired
    private UserPlayInfoMapper userPlayInfoMapper;

    @Autowired
    private UserPlayTimeInfoMapper userPlayTimeInfoMapper;

    public List<UserPlayTimeInfo> getPlayTimeList(long userId, long dateTime) {
        return new BizTemplate<List<UserPlayTimeInfo>>(getClass().getSimpleName() + ".getTimeList") {
            @Override
            protected void checkParams() throws VinciException {
                if (userId <= 0) {
                    throw new VinciException(ErrorCode.ARGUMENT_ERROR, "userId <= 0", "");
                }

                if (dateTime <= 0) {
                    throw new VinciException(ErrorCode.ARGUMENT_ERROR, "dateTime小于0", "");
                }

                UserInfo userInfo = userLoginAndBindDeviceService.getUserInfo(userId, false);
            }

            @Override
            protected List<UserPlayTimeInfo> process() throws Exception {
                Date date = new Date(dateTime);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                calendar.set(Calendar.HOUR_OF_DAY, 0);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MILLISECOND, 0);

                List<UserPlayTimeInfo> list = userPlayTimeInfoMapper.select(userId, calendar.getTime());

                List<Long> userIdList = new ArrayList<Long>(list.size());
                for (UserPlayTimeInfo userPlayTimeInfo : list) {
                    userIdList.add(userPlayTimeInfo.getUserId());
                }

                Map<Long, UserInfo> map = userLoginAndBindDeviceService.getUserInfoMap(userIdList);

                int place = 1;
                for (UserPlayTimeInfo userPlayTimeInfo : list) {
                    userPlayTimeInfo.setUserInfo(map.get(userPlayTimeInfo.getUserId()));
                    userPlayTimeInfo.setPlace(place);
                    userPlayTimeInfo.setCreateTime(date);

                    place++;
                }

                return list;
            }
        }.execute();
    }

    public UserPlayInfo getPlayList(long userId, long dateTime) {
        return new BizTemplate<UserPlayInfo>(getClass().getSimpleName() + ".getPlayList") {
            @Override
            protected void checkParams() throws VinciException {
                if (userId <= 0) {
                    throw new VinciException(ErrorCode.ARGUMENT_ERROR, "userId <= 0", "");
                }

                if (dateTime <= 0) {
                    throw new VinciException(ErrorCode.ARGUMENT_ERROR, "dateTime小于0", "");
                }
            }

            @Override
            protected UserPlayInfo process() throws Exception {
                UserInfo userInfo = userLoginAndBindDeviceService.getUserInfo(userId, false);

                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date(dateTime));
                calendar.set(Calendar.HOUR_OF_DAY, 0);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MILLISECOND, 0);

                Date startTime = calendar.getTime();

                calendar.set(Calendar.HOUR_OF_DAY, 22);
                Date endTime = calendar.getTime();

                List<UserPlayInfoDAO> list = userPlayInfoMapper.select(userId, startTime, endTime);

                int playTimeInSeconds = 0;
                List<MusicPlayInfo> musicPlayInfoList = new ArrayList<MusicPlayInfo>(list.size());
                HashMap<Long, HashMap<String, MusicPlayInfo>> map = new HashMap<Long, HashMap<String, MusicPlayInfo>>();
                for (UserPlayInfoDAO userPlayInfoDAO : list) {
                    MusicSong music = JsonUtils.decode(userPlayInfoDAO.getMusicInfo(), MusicSong.class);

                    playTimeInSeconds = playTimeInSeconds + music.getPlaySeconds();

                    HashMap<String, MusicPlayInfo> tempMap = map.get(music.getSongId());
                    if (tempMap == null) {
                        tempMap = new HashMap<String, MusicPlayInfo>();
                        map.put(music.getSongId(), tempMap);
                    }

                    MusicPlayInfo musicPlayInfo = tempMap.get(music.getSongType());
                    if (musicPlayInfo == null) {
                        musicPlayInfo = new MusicPlayInfo();
                        musicPlayInfo.setMusic(music);

                        tempMap.put(music.getSongType(), musicPlayInfo);
                        musicPlayInfoList.add(musicPlayInfo);
                    }
                    int times = musicPlayInfo.getTimes() + 1;
                    musicPlayInfo.setTimes(times);
                }

                if (!musicPlayInfoList.isEmpty()) {
                    Collections.sort(musicPlayInfoList, new Comparator<MusicPlayInfo>() {
                        @Override
                        public int compare(MusicPlayInfo o1, MusicPlayInfo o2) {
                            if (o1.getTimes() > o2.getTimes()) {
                                return -1;
                            } else if (o1.getTimes() == o2.getTimes()) {
                                return 0;
                            } else {
                                return 1;
                            }
                        }
                    });
                }

                UserPlayInfo userPlayInfo = new UserPlayInfo();
                userPlayInfo.setUserInfo(userInfo);
                userPlayInfo.setSongCount(musicPlayInfoList.size());
                userPlayInfo.setMusicList(musicPlayInfoList);
                userPlayInfo.setCreateTime(new Date(dateTime));

                int durationTime = playTimeInSeconds % 60 == 0 ? playTimeInSeconds / 60 : playTimeInSeconds / 60 + 1;
                userPlayInfo.setDurationTime(durationTime);

                return userPlayInfo;
            }
        }.execute();
    }

    public Boolean isValidPlayList(long userId, long dateTime) {
        return new BizTemplate<Boolean>(getClass().getSimpleName() + ".isValidPlayList") {
            @Override
            protected void checkParams() throws VinciException {
                if (userId <= 0) {
                    throw new VinciException(ErrorCode.ARGUMENT_ERROR, "userId <= 0", "");
                }

                if (dateTime <= 0) {
                    throw new VinciException(ErrorCode.ARGUMENT_ERROR, "dateTime小于0", "");
                }

            }

            @Override
            protected Boolean process() throws Exception {
                UserInfo userInfo = userLoginAndBindDeviceService.getUserInfo(userId, false);

                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date(dateTime));
                calendar.set(Calendar.HOUR_OF_DAY, 0);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MILLISECOND, 0);

                Date startTime = calendar.getTime();

                calendar.set(Calendar.HOUR_OF_DAY, 22);
                Date endTime = calendar.getTime();

                List<UserPlayInfoDAO> list = userPlayInfoMapper.select(userId, startTime, endTime);

                boolean result = true;
                if (list == null || list.isEmpty()) {
                    result = false;
                }

                return result;
            }
        }.execute();
    }

    public static void main(String[] args) {
        long dateTime = 1489593600000L;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date(dateTime));
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        System.out.println(calendar.getTime());
    }
}
